#ifndef _LLCOMP_LLC_H_
#define _LLCOMP_LLC_H_

#ifndef LLC_TRANSLATION

#include </usr/include/mpich2/mpi.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#else

typedef int MPI_Comm;
typedef int MPI_Status;

#endif

typedef struct llc_mem_reg {
    unsigned long addr_start;
    unsigned long addr_stop;
    struct llc_mem_reg *next;
} llc_mem_reg;

typedef struct {
    llc_mem_reg *ptr;
    unsigned long size;
} llc_mem_reg_data;

typedef struct llc_var_reg {
    unsigned long base_addr;
    llc_mem_reg *ptr;
    unsigned long size;
    int num;
} llc_var_reg;

typedef struct {
    llc_var_reg *var_list;
    unsigned long total_size;
    int total_regs;
    int num_var;
} llc_var_reg_data;

void llc_nc_result_destroy_var_list (void);

extern llc_var_reg_data llc_nc_result_list;

int LLC_GLOBAL_NAME;
int LLC_GLOBAL_NUMPROCESSORS;
int LLC_NAME;
int LLC_NUMPROCESSORS;

MPI_Comm llc_GlobalGroup;
MPI_Comm *llc_CurrentGroup;

int llc_nT;
int *llc_F;

#ifndef NULL 
#define NULL ((void *) 0)
#endif

/*********************************************************************
Macro: LLC_printMaster
Description: Only master processor displays.
**********************************************************************/
#define LLC_printMaster if (LLC_GLOBAL_NAME == 0) printf

/*********************************************************************
Macro: LLC_EXIT
Description: Closes a MPI environment and return with an exit code.
**********************************************************************/
#define LLC_EXIT(code) {                                                    \
    MPI_Abort (MPI_COMM_WORLD, code);                                       \
    exit(code);                                                             \
}

/*********************************************************************
Macro: LLC_CHECK_MALLOC
Description: Allocate memory and check the allocation process.
**********************************************************************/
#define LLC_CHECK_MALLOC(buf, buf_size, buf_type) {                         \
    (buf) = (buf_type *) malloc ((buf_size) * sizeof(buf_type));            \
    if ((buf) == NULL) {                                                    \
        LLC_printMaster("Error allocating memory...\n");                    \
        LLC_EXIT(-1);                                                       \
    }                                                                       \
}

/*********************************************************************
Macro: LLC_PROCSGRP
Description: 
**********************************************************************/
#define LLC_PROCSGRP(x) (llc_F[(x) + 1] - llc_F[(x)])

/*********************************************************************
Macro: LLC_MAX
Description: 
**********************************************************************/
#define LLC_MAX(a,b) ((a) > (b) ? (a) : (b))

/*********************************************************************
Function: llc_nc_result_destroy_var_list
Description: 
**********************************************************************/
/*
void llc_nc_result_destroy_var_list (void) {
    register int i;
    llc_mem_reg *paux;

    for (i = 0; i < llc_nc_result_list.num_var; i++) {
        while (llc_nc_result_list.var_list[i].ptr != NULL) {
            paux = llc_nc_result_list.var_list[i].ptr;
            llc_nc_result_list.var_list[i].ptr = paux->next;
            free (paux);
        }
    }
    free (llc_nc_result_list.var_list);
    llc_nc_result_list.var_list = NULL;
    llc_nc_result_list.total_size = 0;
    llc_nc_result_list.total_regs = 0;
    llc_nc_result_list.num_var = 0;
}
*/

#define LLC_TAG_REDUCE_DATA 25

#endif
